#define _WIN32_IE 0x400

#include <windows.h>
#include <windowsx.h>
#include <ddraw.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <shellapi.h>
#include <commctrl.h>
#include <winuser.h>
#include "winstuff.h"
#include "resource.h"
#include "version.h"
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
#include "input/input.h"
#include "osdep/keycodes.h"
#include "input/mouse.h"
#include "mp_msg.h"
#include "aspect.h"
#include "geometry.h"
#include "mp_fifo.h"
#include "libvo/sub.h"
#include "stream/stream.h"
#include <w32_gui.h>

#define USE_REGION 0

#define VOLUMEBAR_W 60
#define VOLUMEBAR_H 20

#define WM_NOTIFYICON     (WM_USER+1973)
#define WM_SHOWCURSOR     (WM_USER+1974)
#define WM_SHOWCONTROLBAR (WM_USER+1975)

#define TIMER_SWITCH_VIEW 100
#define TIMER_HIDE_CURSOR 101

#ifndef WM_XBUTTONDOWN
#define WM_XBUTTONDOWN    0x020B
#define WM_XBUTTONUP      0x020C
#define WM_XBUTTONDBLCLK  0x020D
#endif


HWND hWndGUI=NULL;
HWND hWndGUIFS=NULL;
HWND hWndP=NULL;
HWND hWndControlbar;
HWND hWndSeekbar;
HWND hWndVolumebar;
long WM_TASKBARCREATED;
HBITMAP hLogo;
RECT                 rd;                     //rect of our stretched image
RECT                 rs;                     //rect of our source image
HBRUSH               blackbrush = NULL;      // Handle to black brush
HBRUSH               colorbrush = NULL;      // Handle to colorkey brush
HBRUSH               bkgndbrush = NULL;
HICON                mplayericon = NULL;     // Handle to mplayer icon
HCURSOR              mplayercursor = NULL;   // Handle to mplayer cursor
int logoW, logoH;
int SeekbarWidth;
int ControlbarShow = TRUE;
int xborder,yborder;
BOOL bFullView = TRUE;
BOOL bRBDown = FALSE;
BOOL bWheel = FALSE;
int WndState = SW_NORMAL;
int save_vo_fs = -1;
#if !USE_REGION
int xborder0,yborder0;
int xborder1,yborder1;
#endif

HANDLE hAccelTable;
int systray = 0;
int switch_view = 0;
int auto_hide = 2000;
int fixedsize = 0;
int bSeeking = 0;

#ifdef USE_ICONV
extern char *sub_cp;
char AlternativeFont[MAX_PATH];
#endif

HMENU hMenu, hSubtitleMenu, hPopupMenu;
MENUITEMINFO mi;
RECT monitor_rect;
NOTIFYICONDATA nid;
COLORREF windowcolor = RGB(0,0,16);          //windowcolor == colorkey

int menuHeight;
int bIdle;
float window_aspect;
int adapter_count=0;
int paused = 0;
int delta_x=0,delta_y=0;
float factors[3] = {0, -0.1875, -0.2975};
int factor_index = 0;
float factor_x=0,factor_y=0;
DWORD start_lbutton_down;



extern int force_load_font;
extern int use_cuspal;
extern int reverse_pal;
extern int spu_pal;
extern int save_volume;
extern char *sub_font_name;
extern float text_font_scale_factor;
extern int sub_pos;
extern char *filename;
extern char *dvd_device;
extern float expand;


int disp_height,disp_top;
uint32_t d_image_width, d_image_height;      //image width and height zoomed

int disable_manage = 0;



HANDLE hAccelTable;

int FullHide;
int bHide=FALSE;

int old_x, old_y, bMoving = MOVING_NONE;

static void onresize()
{
    int width,height,top=0;

    if(vo_fs){
        aspect(&width,&height,A_ZOOM);
        if (!vo_keepaspect)
        {
            width = vo_screenwidth;
            height = vo_screenheight;
		}
		rd.left=(vo_screenwidth-width)/2;
		if (expand >= 0)
		  rd.top=(vo_screenheight-height)/2;
		else
		  rd.top=(vo_screenheight+height*expand+1)/2;

        SeekbarWidth = vo_screenwidth - VOLUMEBAR_W;
        SetWindowPos(hWndVolumebar,NULL,SeekbarWidth,0,VOLUMEBAR_W,VOLUMEBAR_H,SWP_NOZORDER|SWP_NOOWNERZORDER);
        SetWindowPos(hWndSeekbar,NULL,0,0,SeekbarWidth,VOLUMEBAR_H,SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER);
		SetWindowPos(hWndControlbar,NULL,0,vo_screenheight-VOLUMEBAR_H+4,vo_screenwidth,VOLUMEBAR_H,SWP_NOZORDER|SWP_NOOWNERZORDER);
    }
    else {
    	GetClientRect(hWndGUI, &rd);
        width = rd.right;
	    height = rd.bottom - VOLUMEBAR_H;
        SeekbarWidth = width - VOLUMEBAR_W;
    	SetWindowPos(hWndControlbar,NULL,0,height,width,VOLUMEBAR_H,SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
        SetWindowPos(hWndVolumebar,NULL,SeekbarWidth,0,VOLUMEBAR_W,VOLUMEBAR_H,SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
        SetWindowPos(hWndSeekbar,NULL,0,0,SeekbarWidth,VOLUMEBAR_H,SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
    	PostMessage(hWndGUI, WM_SHOWCONTROLBAR, 0, 0);
    }
}

static void w32_fullscreen()
{
    save_vo_fs = vo_fs = vo_fs?0:1;
    onresize();
    if (vo_fs) {
        static MENUITEMINFO mi_close = {
            sizeof(MENUITEMINFO),
            MIIM_ID|MIIM_TYPE,
            MFT_RIGHTJUSTIFY|MFT_STRING,
            MFS_ENABLED,
            IDM_CLOSE,
            NULL,
            0,
            0,
            0,
            "X",
            1
        };
        ShowWindow(hWndGUI, SW_HIDE);
        InsertMenuItem(hMenu, 0xFFFFFFFF, TRUE, &mi_close);
        ShowWindow(hWndGUIFS, SW_SHOW);
        BringWindowToTop(hWndGUIFS);
        ShowWindow(hWndControlbar, SW_HIDE);
        SetParent(hWndControlbar, hWndGUIFS);
        ControlbarShow = FALSE;
        PostMessage(hWndGUIFS, WM_MOUSEMOVE, 0, 0x400000);
        InvalidateRect(hWndGUIFS, NULL, TRUE);
    } else {
        KillTimer(hWndGUIFS, TIMER_HIDE_CURSOR);
        SetParent(hWndControlbar, hWndGUI);
        ShowWindow(hWndControlbar, SW_SHOW);
        DeleteMenu(hMenu, IDM_CLOSE, MF_BYCOMMAND);
        ShowWindow(hWndGUI, SW_SHOW);
        ShowWindow(hWndGUIFS, SW_HIDE);
        BringWindowToTop(hWndGUI);
        SetForegroundWindow(hWndGUI);
        PostMessage(hWndGUI, WM_SHOWCURSOR, 0, 0);
    }
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if ( message == WM_TASKBARCREATED )
	{
	 	Shell_NotifyIcon(NIM_ADD, &nid);
		return 0;
	}

	switch (message)
    {
		case WM_ERASEBKGND:
		{
			RECT rc;
			GetClientRect(hWnd, &rc);
			if (bIdle) {
				HDC dc1 = CreateCompatibleDC((HDC)wParam);
				HDC dc2 = CreateCompatibleDC((HDC)wParam);
				HBITMAP bmp = CreateCompatibleBitmap((HDC)wParam, rc.right, rc.bottom);
				SelectObject(dc1, bmp);
				SelectObject(dc2, hLogo);
				FillRect(dc1, &rc, bkgndbrush);
				BitBlt(dc1,	(rc.right+rc.left-logoW)>>1, (rc.bottom+rc.top-logoH)>>1,
					logoW, logoH, dc2, 0, 0, SRCCOPY);
				BitBlt((HDC)wParam, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
					dc1, rc.left, rc.top, SRCCOPY);
				DeleteObject(bmp);
				DeleteDC(dc1);
				DeleteDC(dc2);
			}
			InvalidateRect(hWndVolumebar, NULL, FALSE);
		}
        case WM_COMMAND:
	    {
	   		char tmps[MAX_PATH];
			char *filename;

			if (LOWORD(wParam) >= IDM_SUBTITLE) {
				CheckMenuRadioItem(hSubtitleMenu, IDM_SUBTITLE, IDM_SUBTITLE + 99,
					LOWORD(wParam), MF_BYCOMMAND);
				sprintf(tmps, "sub_select %d", LOWORD(wParam) - IDM_SUBTITLE - 1);
				mp_input_queue_cmd(mp_input_parse_cmd(tmps));
				return 0;
			}

		   	switch (LOWORD(wParam)) {
				case IDM_OPEN:
				case IDM_ADD: {
					char *cmdline = NULL;
					BOOL bOpen = LOWORD(wParam)==IDM_OPEN;
					int i = GetOpenFile(bOpen?"Open File(s) to Play":"Add File(s) to Playlist",
						&filename, bOpen?&cmdline:NULL);
					if (i==1)
						sprintf(tmps, "%slist \"%s\"", bOpen?"load":"add", filename);
					else if (i==2)
						sprintf(tmps, "%sfile \"%s\"", bOpen?"load":"add", filename);
					else
						break;
					mp_parse_commandline(cmdline);
					mp_input_queue_cmd(mp_input_parse_cmd(tmps));
					break;
				}
				case IDM_LOAD_SUB:
					if (GetSubFile(&filename)) {
						sprintf(tmps, "sub_load \"%s\"", filename);
						mp_input_queue_cmd(mp_input_parse_cmd(tmps));
					}
					break;
				case IDM_SWITCH_FONT:
					mp_input_queue_cmd(mp_input_parse_cmd("switch_font"));
					break;
				case IDM_SUB_FONT:
					if (GetFontFile(AlternativeFont)) {
						sub_font_name = AlternativeFont;
						force_load_font = 1;
						vo_osd_changed(OSDTYPE_SUBTITLE);
					}
					break;
				case IDM_EXIT:
				case IDM_CLOSE:
					mp_input_queue_cmd(mp_input_parse_cmd("quit"));
					break;
				case IDM_KEEP_ASPECT:
					vo_keepaspect = !vo_keepaspect;
					CheckMenuItem(hMenu, IDM_KEEP_ASPECT, vo_keepaspect?MF_CHECKED:MF_UNCHECKED);
					break;
				case IDM_FIXED_SIZE:
					fixedsize = !fixedsize;
					CheckMenuItem(hMenu, IDM_FIXED_SIZE, fixedsize?MF_CHECKED:MF_UNCHECKED);
					break;
				case IDM_CUSPAL:
					use_cuspal = !use_cuspal;
					CheckMenuItem(hMenu, IDM_CUSPAL, use_cuspal?MF_CHECKED:MF_UNCHECKED);
					break;
				case IDM_REVPAL:
					reverse_pal = !reverse_pal;
					CheckMenuItem(hMenu, IDM_REVPAL, reverse_pal?MF_CHECKED:MF_UNCHECKED);
					break;
				case IDM_HOMEPAGE:
					ShellExecute(0, NULL, "http://www.mplayerhq.hu", NULL, NULL, SW_NORMAL);
					break;
				case IDM_MANPAGE:
					filename = get_path("man_page.html");
					if (GetFileAttributes(filename) == 0xFFFFFFFF)
						ShellExecute(0, NULL, "http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html", NULL, NULL, SW_NORMAL);
					else
						ShellExecute(0, NULL, filename, NULL, NULL, SW_NORMAL);
					free(filename);
					break;
				case IDM_CMDLINE:
					MessageBox(hWndGUI, get_help_text(), "MPlayer", MB_OK | MB_ICONEXCLAMATION | (vo_ontop?MB_TOPMOST:0));
					break;
				case IDM_CONFIG:
				case IDM_INPUT_CONF:
				case IDM_LOG:
				{
					static char *fnames[] = {
						"mplayer.ini", "input.ini", "log.txt"
					};
					filename = get_path(fnames[LOWORD(wParam) - IDM_CONFIG]);
					ShellExecute(0, NULL, filename, NULL, NULL, SW_NORMAL);
					free(filename);
					break;
				}
				case IDM_ABOUT: {
					MSGBOXPARAMS mp;
					memset(&mp, 0, sizeof(mp));
					mp.cbSize = sizeof(mp);
					mp.hwndOwner = hWndGUI;
					mp.hInstance = GetModuleHandle(NULL);
					mp.lpszText = "MPlayer for Windows "VERSION"\n\nCopyright (C) 2000-2007 MPlayer Team\n\n\nMPlayer is distributed under the terms of the GNU\n General Public License Version 2. \nSourcecode is available at http://www.mplayerhq.hu";
					mp.lpszCaption = "About";
					mp.dwStyle = MB_USERICON | MB_OK | (vo_ontop?MB_TOPMOST:0);
					mp.lpszIcon = (LPSTR)IDI_APPICON;
					MessageBoxIndirect(&mp);
					break;
				}
	   		}
		   	return 0;
	    }
        case WM_DROPFILES:
	    {
			char tmps[MAX_PATH];
			int i=0, j=DragQueryFileA((HDROP)wParam, -1,  NULL, 0);
			if (j == 1) {
				char * sub_exts[] = {  "utf", "utf8", "utf-8", "idx", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL};
				char *tmp_fname_ext;

				DragQueryFileA((HDROP)wParam, 0, tmps, MAX_PATH-1);
				if (tmp_fname_ext = strrchr(tmps,'.')) tmp_fname_ext++;
#ifdef USE_ICONV
				for (i = (sub_cp ? 3 : 0); sub_exts[i]; i++) {
#else
				for (i = 0; sub_exts[i]; i++) {
#endif
					if (!stricmp(sub_exts[i], tmp_fname_ext)) {
						char *filename = strdup(tmps);
						sprintf(tmps, "sub_load \"%s\"", filename);
						free(filename);
						mp_input_queue_cmd(mp_input_parse_cmd(tmps));
						goto EndDrag;
					}
				}
				if (GetKeyState(VK_CONTROL) < 0)
					strcpy(tmps, "addfile \"");
				else
					strcpy(tmps, "loadfile \"");
				DragQueryFileA((HDROP)wParam, 0, tmps+strlen(tmps), MAX_PATH-strlen(tmps)-1);
				strcat(tmps, "\"");
			} else {
				FILE * fp = fopen(mplayer_pls, "w");
				while (i<j) {
					DragQueryFileA((HDROP)wParam, i++, tmps, MAX_PATH);
					fprintf(fp, "%s\n", tmps);
				}
				fclose(fp);
				if (GetKeyState(VK_CONTROL) < 0)
					sprintf(tmps, "addlist \"%s\"", mplayer_pls);
				else
					sprintf(tmps, "loadlist \"%s\"", mplayer_pls);
			}
			mp_input_queue_cmd(mp_input_parse_cmd(tmps));
EndDrag:
			DragFinish((HDROP)wParam);

			SetForegroundWindow(hWndGUI);
			return 0;
       	}
		case WM_TIMER:
			switch (wParam) {
    			case TIMER_HIDE_CURSOR:
    				if (!GetMenu(hWndGUI))
    					while(ShowCursor(FALSE)>=0);
    				KillTimer(hWndGUIFS, TIMER_HIDE_CURSOR);
    				break;
            }
			return 0;
        case WM_MOUSEMOVE:
        	{
        		static DWORD lastp=0;
        		if (lastp != lParam)
        		{
        			lastp = lParam;

        			if (bMoving == MOVING_WINDOW) {
        				RECT r;
        				GetWindowRect(hWndGUI, &r);
        				SetWindowPos(hWndGUI, NULL,
        					r.left+LOWORD(lastp)-old_x,
        					r.top+HIWORD(lastp)-old_y, 0,0,
        					SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
        			}
        			if (vo_fs) {
        				if (vo_fs) {
        					if (GetMenu(hWnd)) {
        						SetMenu(hWnd, NULL);
        					}
        					else if (HIWORD(lParam) < menuHeight) {
        						SetMenu(hWnd, hMenu);
        					}
        				}

        				if (ControlbarShow && HIWORD(lParam) < monitor_rect.bottom-VOLUMEBAR_H+4) {
        					ControlbarShow = FALSE;
        					ShowWindow(hWndControlbar, SW_HIDE);
        				} else
        				if (!ControlbarShow && HIWORD(lParam) >= monitor_rect.bottom-VOLUMEBAR_H+4) {
        					if (bHide) {
        						bHide = FALSE;
        						ShowCursor(TRUE);
        					} else
        						KillTimer(hWndGUIFS, TIMER_HIDE_CURSOR);
        					ControlbarShow = TRUE;
        					ShowWindow(hWndControlbar, SW_SHOW);
        				}
        			}
        		}
        		return 0;
        	}
        case WM_SIZING:
        	{
        		if (!vo_fs && vo_keepaspect)
        		{
        			LPRECT rc = (LPRECT)lParam;
        			switch (wParam)
        			{
        				case WMSZ_LEFT:
        				case WMSZ_RIGHT:
        					rc->bottom = rc->top+(rc->right-rc->left-xborder)/window_aspect+yborder+0.5;
        					break;
        				case WMSZ_TOP:
        				case WMSZ_BOTTOM:
        				case WMSZ_TOPRIGHT:
        				case WMSZ_BOTTOMRIGHT:
        					rc->right = rc->left+(rc->bottom-rc->top-yborder)*window_aspect+xborder+0.5;
        					break;
        				case WMSZ_TOPLEFT:
        				case WMSZ_BOTTOMLEFT:
        					rc->left = rc->right-(rc->bottom-rc->top-yborder)*window_aspect-xborder+0.5;
        					break;
        			}
        			return 0;
        		}
        		break;
        	}
        case WM_SIZE:
            onresize();
            break;
        case WM_SHOWCURSOR:
        	ShowCursor(TRUE);
        	return 0;
        case WM_SHOWCONTROLBAR:
        	InvalidateRect(hWndControlbar, NULL, TRUE);
        	return 0;
        case WM_NOTIFYICON:
        {
        	switch (lParam) {
        		case WM_LBUTTONDOWN:
        			if (WndState == SW_SHOWMINIMIZED) {
        				if (paused && systray==2) mp_input_queue_cmd(mp_input_parse_cmd("pause"));
        				PostMessage(hWndGUI, WM_SYSCOMMAND, SC_RESTORE, 0);
        			}
        			SetForegroundWindow(hWndGUI);
        			break;
        		case WM_LBUTTONDBLCLK:
        			SendMessage(hWndGUI, WM_COMMAND, IDM_OPEN, 0);
        			SetForegroundWindow(hWndGUI);
        			break;
        		case WM_RBUTTONDOWN: {
        			POINT p;
        			SetForegroundWindow(hWndGUI);
        			GetCursorPos(&p);
        			TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, p.x, p.y, 0, hWndGUI, NULL);
        			break;
        		}
        	}
        	return 0;
        }
        case WM_SYSCHAR:
		{
			if (wParam == 13) {
				w32_fullscreen();
			} 
			return 0;
		}
	    case WM_NCACTIVATE:
        {
            if(adapter_count > 2) //only disable if more than one adapter.
			    return 0;
			break;
		}
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}
        case WM_CLOSE:
		{
			mplayer_put_key(KEY_CLOSE_WIN);
			return 0;
		}
        case WM_SYSCOMMAND:
		{
			LRESULT ret;
			WINDOWPLACEMENT wp;

			switch (wParam)
			{   //kill screensaver etc.
				//note: works only when the window is active
				//you can workaround this by disabling the allow screensaver option in
				//the link to the app
				case SC_SCREENSAVE:
				case SC_MONITORPOWER:
			        mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>killing screensaver\n" );
                	return 0;
				case SC_MINIMIZE:
					if (hWndP) {
						ShowWindow(hWndGUI, SW_MINIMIZE);
						ShowWindow(hWndGUI, SW_HIDE);
						if (!paused && systray==2) mp_input_queue_cmd(mp_input_parse_cmd("pause"));
					}
					break;
			}

			ret = DefWindowProc(hWnd, message, wParam, lParam);
			GetWindowPlacement(hWndGUI, &wp);
			WndState = wp.showCmd;

			return ret;
		}
        case WM_KEYDOWN:
		{
			if ( (vo_fs) && (wParam >= VK_NUMPAD1) && (wParam <= VK_DECIMAL)) {
				if (GetKeyState(VK_LCONTROL) < 0) {
					switch (wParam) {
						case VK_NUMPAD1 : delta_x -= 4; delta_y += 4; break;
						case VK_NUMPAD2 : delta_y += 4; break;
						case VK_NUMPAD3 : delta_x += 4; delta_y += 4; break;
						case VK_NUMPAD4 : delta_x -= 4; break;
						case VK_NUMPAD5 : delta_x = delta_y = 0; break;
						case VK_NUMPAD6 : delta_x += 4; break;
						case VK_NUMPAD7 : delta_x -= 4; delta_y -= 4; break;
						case VK_NUMPAD8 : delta_y -= 4; break;
						case VK_NUMPAD9 : delta_x += 4; delta_y -= 4; break;
						case VK_ADD     :
						case VK_SUBTRACT:
							spu_pal = ((spu_pal+((wParam==VK_ADD)?136:120))&0xFF)-128;
							return 0;
					}
					break;
				}
				else if (GetKeyState(VK_RCONTROL) < 0) {
					vo_keepaspect = 0;
					switch (wParam) {
						case VK_NUMPAD1 : factor_x = (1 + factor_x) * 0.98 - 1; factor_y = (1 + factor_y) * 0.98 - 1; break;
						case VK_NUMPAD2 : factor_y -= 0.02; break;
						case VK_NUMPAD3 : factor_x = 0; factor_y = factors[factor_index = (factor_index+1) % 3]; break;
						case VK_NUMPAD4 : factor_x -= 0.02; break;
						case VK_NUMPAD5 : factor_x = factor_y = 0; vo_keepaspect = 1; break;
						case VK_NUMPAD6 : factor_x += 0.02; break;
						case VK_NUMPAD7 : factor_x = 0; factor_y = factors[factor_index = (factor_index+2) % 3]; break;
						case VK_NUMPAD8 : factor_y += 0.02; break;
						case VK_NUMPAD9 : factor_x = (1 + factor_x) * 1.02 - 1; factor_y = (1 + factor_y) * 1.02 - 1; break;
					}
					CheckMenuItem(hMenu, IDM_KEEP_ASPECT, vo_keepaspect?MF_CHECKED:MF_UNCHECKED);
					break;
				}
			}

			switch (wParam)
			{
				case VK_LEFT:
					{mplayer_put_key(KEY_LEFT);break;}
				case VK_UP:
					{mplayer_put_key(KEY_UP);break;}
				case VK_RIGHT:
					{mplayer_put_key(KEY_RIGHT);break;}
				case VK_DOWN:
					{mplayer_put_key(KEY_DOWN);break;}
				case VK_TAB:
					{mplayer_put_key(KEY_TAB);break;}
				case VK_BACK:
					{mplayer_put_key(KEY_BS);break;}
				case VK_DELETE:
					{mplayer_put_key(KEY_DELETE);break;}
		        case VK_INSERT:
					{mplayer_put_key(KEY_INSERT);break;}
		        case VK_HOME:
					{mplayer_put_key(KEY_HOME);break;}
		        case VK_END:
					{mplayer_put_key(KEY_END);break;}
		        case VK_PRIOR:
			        {mplayer_put_key(KEY_PAGE_UP);break;}
		        case VK_NEXT:
			        {mplayer_put_key(KEY_PAGE_DOWN);break;}
		        case VK_ESCAPE:
					{mplayer_put_key(KEY_ESC);break;}
				default:
			 		if (wParam >= VK_F1 && wParam <= VK_F12)
						mplayer_put_key((KEY_F+1-VK_F1)+wParam);
			}
            break;
		}
        case WM_CHAR:
		{
			mplayer_put_key(wParam);
			break;
		}
        case WM_LBUTTONDOWN:
		{
			start_lbutton_down = GetTickCount();
            old_x = LOWORD(lParam);
            old_y = HIWORD(lParam);
			if (!bMoving) {
				if (!vo_fs && WndState != SW_SHOWMAXIMIZED)
				{
					bMoving = MOVING_WINDOW;
				}
			}
			break;
        }

        case WM_LBUTTONUP:
		{
			bMoving = MOVING_NONE;
			if (!vo_nomouse_input && GetTickCount()-start_lbutton_down<500)
				mplayer_put_key(MOUSE_BTN0);
			break;
		}
        case WM_MBUTTONDOWN:
		{
			if (!vo_nomouse_input)
				mplayer_put_key(MOUSE_BTN1);
			break;
		}
        case WM_RBUTTONDOWN:
		{
			bRBDown = TRUE;
			bWheel = FALSE;
			break;
        }
        case WM_RBUTTONUP:
		{
			bRBDown = FALSE;
			if (!vo_nomouse_input && !bWheel)
				mplayer_put_key(MOUSE_BTN2);
			break;
		}
		case WM_LBUTTONDBLCLK:
		{
			if(!vo_nomouse_input)
				mplayer_put_key(MOUSE_BTN0_DBL);
			break;
		}
		case WM_MBUTTONDBLCLK:
		{
			if (!vo_nomouse_input)
				mplayer_put_key(MOUSE_BTN1_DBL);
			break;
		}
		case WM_RBUTTONDBLCLK:
		{
			if (!vo_nomouse_input)
				mplayer_put_key(MOUSE_BTN2_DBL);
			break;
		}
        case WM_MOUSEWHEEL:
		{
			int x;

			bWheel = TRUE;
			if (vo_nomouse_input)
				break;
			x = GET_WHEEL_DELTA_WPARAM(wParam);
			if (x > 0)
				mplayer_put_key(bRBDown?MOUSE_BTN8:MOUSE_BTN3);
			else
				mplayer_put_key(bRBDown?MOUSE_BTN9:MOUSE_BTN4);
			break;
		}
        case WM_XBUTTONDOWN:
		{
			if (vo_nomouse_input)
				break;
			if (HIWORD(wParam) == 1)
				mplayer_put_key(MOUSE_BTN5);
			else
				mplayer_put_key(MOUSE_BTN6);
			break;
		}
        case WM_XBUTTONDBLCLK:
		{
			if (vo_nomouse_input)
				break;
			if (HIWORD(wParam) == 1)
				mplayer_put_key(MOUSE_BTN5_DBL);
			else
				mplayer_put_key(MOUSE_BTN6_DBL);
			break;
		}

    }
	return DefWindowProc(hWnd, message, wParam, lParam);
}

static BOOL CALLBACK ControlbarProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
   		case WM_NOTIFY:
			SetFocus(vo_fs?hWndGUIFS:hWndGUI);
    	    break;
    	case WM_HSCROLL:
		{
			char tmps[20];
	    	POINT p;
			float x;

			SetFocus(vo_fs?hWndGUIFS:hWndGUI);
			GetCursorPos(&p);
			ScreenToClient((HWND)lParam, &p);
			if ((HWND)lParam == hWndSeekbar)
				x = (p.x-10)*100.0/(SeekbarWidth-20);
			else
				x = (p.x-10)*100/(VOLUMEBAR_W-20);
			SendMessage((HWND)lParam, TBM_SETPOS, TRUE, (LPARAM)x);
			if (!bSeeking && (LOWORD(wParam)==TB_ENDTRACK || LOWORD(wParam)==TB_THUMBTRACK)) {
				if ((HWND)lParam == hWndSeekbar) {
					bSeeking = 1;
					sprintf(tmps, "seek %f 1", x);
				} else {
					sprintf(tmps, "volume %d 1", (int)x);
				}
				mp_input_queue_cmd(mp_input_parse_cmd(tmps));
			}
			return TRUE;
	    }
	}

	return FALSE;
}

int init_window(void)
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    WNDCLASS wc;
	RECT rd;
	BITMAP bm;
	memset(&rd, 0, sizeof(rd));
    AdjustWindowRect(&rd,WNDSTYLE,TRUE);
	xborder = rd.right - rd.left;
	yborder = rd.bottom - rd.top + VOLUMEBAR_H;
#if !USE_REGION
	xborder0 = xborder;
	yborder0 = yborder;
	memset(&rd, 0, sizeof(rd));
    AdjustWindowRect(&rd,WS_POPUP|WS_THICKFRAME,FALSE);
	xborder1 = (rd.right - rd.left) >> 1;
	yborder1 = (rd.bottom - rd.top) >> 1;
#endif

    if (systray) hWndP = CreateWindow("Static",NULL,WS_POPUP,0,0,0,0,NULL,NULL,hInstance,NULL);

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR));
	hLogo = LoadImage(hInstance, MAKEINTRESOURCE(IDI_MPLAYER_LOGO), IMAGE_BITMAP, 0, 0, 0);
	GetObject(hLogo, sizeof(BITMAP), &bm);
	logoW = bm.bmWidth;
	logoH = bm.bmHeight;

	/*load icon from the main app*/
	mplayericon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
    if(!mplayericon) mplayericon = LoadIcon(NULL, IDI_APPLICATION);
    mplayercursor = LoadCursor(NULL, MAKEINTRESOURCE(0x7F89));
    monitor_rect.right = GetSystemMetrics(SM_CXSCREEN);
    monitor_rect.bottom = GetSystemMetrics(SM_CYSCREEN);

    windowcolor = vo_colorkey;
    bkgndbrush = CreateSolidBrush(RGB(0,0,16));
    colorbrush = CreateSolidBrush(windowcolor);
    blackbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.style         =  CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    wc.lpfnWndProc   =  WndProc;
    wc.cbClsExtra    =  0;
    wc.cbWndExtra    =  0;
    wc.hInstance     =  hInstance;
    wc.hCursor       =  mplayercursor;
    wc.hIcon         =  mplayericon;
    wc.hbrBackground =  colorbrush;
    wc.lpszClassName =  WNDCLASSNAME_WINDOWED;
    wc.lpszMenuName  =  MAKEINTRESOURCE(IDR_MAINMENU);
    RegisterClass(&wc);
    if (WinID != -1) hWndGUI = (HWND)WinID;
    else
    hWndGUI = CreateWindowEx(0,
        WNDCLASSNAME_WINDOWED,"MPlayer",
        /*WS_VISIBLE|*/WNDSTYLE,
        (monitor_rect.right - 320)>>1, (monitor_rect.bottom - 300)>>1,
        320, 300,hWndP,NULL,hInstance,NULL);
    DragAcceptFiles(hWndGUI, TRUE);
    window_aspect = (float)(320-xborder) / (float)(300-yborder);

    hMenu = GetMenu(hWndGUI);
    menuHeight = GetSystemMetrics(SM_CYMENU);
	memset(&mi, 0, sizeof(mi));
	mi.cbSize = sizeof(mi);
	mi.fMask = MIIM_ID | MIIM_TYPE;
	mi.fType = MFT_STRING | MFT_RADIOCHECK;

    if (hWndP) {
	hPopupMenu = CreatePopupMenu();
	AppendMenu(hPopupMenu,
		MF_POPUP|MF_STRING,
		(UINT)GetSubMenu(hMenu, 0),
		"&File");
	AppendMenu(hPopupMenu,
		MF_POPUP|MF_STRING,
		(UINT)GetSubMenu(hMenu, 1),
		"&Option");
	AppendMenu(hPopupMenu,
		MF_POPUP|MF_STRING,
		(UINT)GetSubMenu(hMenu, 2),
		"&Help");
	AppendMenu(hPopupMenu, MF_SEPARATOR, 0, NULL);
	InsertMenu(hPopupMenu, -1, MF_STRING|MF_BYPOSITION, IDM_EXIT, "E&xit");

	WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
	nid.cbSize = sizeof(nid);
	nid.hWnd = hWndGUI;
	nid.uID = 1973;
	nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
	nid.hIcon = mplayericon;
	nid.uCallbackMessage = WM_NOTIFYICON;
	strcpy(nid.szTip, "MPlayer");
	Shell_NotifyIcon(NIM_ADD, &nid);
    }

	hWndControlbar = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONTROL), hWndGUI, ControlbarProc);
    hWndSeekbar = GetDlgItem(hWndControlbar, IDC_SEEK);
    hWndVolumebar = GetDlgItem(hWndControlbar, IDC_VOLUME);
    PostMessage(hWndSeekbar, TBM_SETRANGEMAX, FALSE, 100);
    PostMessage(hWndVolumebar, TBM_SETRANGEMAX, FALSE, 100);
    PostMessage(hWndVolumebar, TBM_SETPOS, TRUE, save_volume);

    wc.lpszMenuName  = NULL;
    wc.hbrBackground = blackbrush;
    wc.lpszClassName = WNDCLASSNAME_FULLSCREEN;
    RegisterClass(&wc);
    
    hWndGUIFS = CreateWindow(WNDCLASSNAME_FULLSCREEN,"MPlayer Fullscreen",WS_POPUP,monitor_rect.left,monitor_rect.top,monitor_rect.right-monitor_rect.left,monitor_rect.bottom-monitor_rect.top,hWndGUI,NULL,hInstance,NULL);

	int width,height,top=0;
	POINT pt;
	#if USE_REGION
	GetClientRect(hWndGUI, &rd);
	width = rd.right;
	height = rd.bottom - VOLUMEBAR_H;
	#else
	if (bFullView) {
		GetClientRect(hWndGUI, &rd);
		width = rd.right;
		height = rd.bottom - VOLUMEBAR_H;
	} else {
		GetWindowRect(hWndGUI, &rd);
		width = rd.right - rd.left;
		height = rd.bottom - rd.top;
	}
	#endif
        
    vo_screenwidth = monitor_rect.right - monitor_rect.left;
    vo_screenheight = monitor_rect.bottom - monitor_rect.top;
	SeekbarWidth = width - VOLUMEBAR_W;
	SetWindowPos(hWndControlbar,NULL,0,height,width,VOLUMEBAR_H,SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
	SetWindowPos(hWndVolumebar,NULL,SeekbarWidth,0,VOLUMEBAR_W,VOLUMEBAR_H,SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
	SetWindowPos(hWndSeekbar,NULL,0,0,SeekbarWidth,VOLUMEBAR_H,SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSENDCHANGING);
	PostMessage(hWndGUI, WM_SHOWCONTROLBAR, 0, 0);
	FullHide = FALSE;
    
    CheckMenuItem(hMenu, IDM_KEEP_ASPECT, vo_keepaspect?MF_CHECKED:MF_UNCHECKED);
    CheckMenuItem(hMenu, IDM_FIXED_SIZE, fixedsize?MF_CHECKED:MF_UNCHECKED);
    CheckMenuItem(hMenu, IDM_REVPAL, reverse_pal?MF_CHECKED:MF_UNCHECKED);
    CheckMenuItem(hMenu, IDM_CUSPAL, use_cuspal?MF_CHECKED:MF_UNCHECKED);
    EnableMenuItem(hMenu, IDM_CUSPAL, spu_pal?MF_GRAYED:MF_ENABLED);
    return 0;
}